import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.regex.Pattern;

import org.jsoup.Jsoup;

public class Parser {
	
	
	// Class variables
	private String mMainFolder;
	private Path rootDir;
	private StringBuilder fileContent;
	protected String FILE_NAME = "files.txt"; 

	/**
	 * Class constructor
	 * 
	 * @param mainFolder
	 *            The root folder contains the HTML files to parse
	 */
	public Parser(String mainFolder) {
		mMainFolder = mainFolder;
		fileContent = new StringBuilder();
	}
	
	public class DocsContent
	{
		String mData;
		public DocsContent(String data)
		{
			mData = data;
		}
		
		public DocsContent(DocsContent doc_content)
		{
			mData = doc_content.mData;
		}
		
		@Override
		public String toString() {
			return mData; 
		}		
	}
	
	protected void AddFileToDb(DocsContent doc_content, String doc_path)
	{
		fileContent.append(doc_content);
		fileContent.append(System.lineSeparator());		
	}

	/**
	 * Parses the files in the directory - grab each file strip it from it's
	 * content and then add it to the files list
	 * 
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public void ParseDirectoryFiles() throws IOException, InterruptedException {
		getFiles();
		writeToFile(fileContent.toString().trim());
	}

	/**
	 * Extracts the text from a given file
	 * @param reader An object with a refernce to an open file object
	 * @return A string of the stripped down string context of a file
	 * @throws IOException
	 */
	private DocsContent extractText(Reader reader) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader br = new BufferedReader(reader);
		String line;
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		//System.out.println(sb.toString());
		int tag = sb.toString().toLowerCase().indexOf("<html>");
		if(tag > 0) {
			DocsContent textOnly = new  DocsContent(Jsoup.parse(sb.toString().substring(tag)).text());
			return textOnly;
		}
		tag = sb.toString().toLowerCase().indexOf("<title>");
		if(tag > 0) {
			DocsContent textOnly = new DocsContent(Jsoup.parse(sb.toString().substring(tag)).text());
			return textOnly;
		}
		tag = sb.toString().toLowerCase().indexOf("text/html");
		if(tag > 0) {
			DocsContent textOnly = new DocsContent(Jsoup.parse(sb.toString().substring(tag+9)).text());
			return textOnly;
		}
		String textOnly = Jsoup.parse(sb.toString()).text();
		return new DocsContent(textOnly);
	}

	/**
	 * Get the files in the root directory  
	 * @throws IOException
	 * @throws InterruptedException
	 */
	private void getFiles() throws IOException, InterruptedException {
		rootDir = Paths.get(mMainFolder);
		
		// Traverse the file tree starting from a given root folder
		Files.walkFileTree(rootDir, new FileVisitor<Path>() {
			private Pattern pattern = Pattern.compile("^(.*?)");

			@Override
			public FileVisitResult preVisitDirectory(Path path,
					BasicFileAttributes atts) throws IOException {
				boolean matches = pattern.matcher(path.toString()).matches();
				return (matches) ? FileVisitResult.CONTINUE
						: FileVisitResult.SKIP_SUBTREE;
			}

			@Override
			public FileVisitResult visitFile(Path path,
					BasicFileAttributes mainAtts) throws IOException {
				boolean matches = pattern.matcher(path.toString()).matches();
				if (matches) {
					File fileToParse = path.toFile();
					Reader reader = new FileReader(fileToParse);
					DocsContent textFromFile = extractText(reader);
					AddFileToDb(textFromFile,path.toString());
					//fileContent.append(textFromFile);
					//fileContent.append(System.lineSeparator());
					reader.close();
				}
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path path, IOException exception)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult visitFileFailed(Path path, IOException exception)
					throws IOException {
				exception.printStackTrace();
				return path.equals(rootDir) ? FileVisitResult.TERMINATE
						: FileVisitResult.CONTINUE;
			}
		});

	}

	/**
	 * Write the content of a string to file
	 * @param content The content to write to the file
	 * @throws IOException
	 */
	private void writeToFile(String content) throws IOException {
		File file = new File(FILE_NAME);

		if (!file.exists()) {
			file.createNewFile();
		}

		FileWriter fw = new FileWriter(file.getAbsoluteFile());
		BufferedWriter bw = new BufferedWriter(fw);
		bw.write(content);
		bw.close();
	}
}
